package solver.moves;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import model.Solution;
import model.SolverEnvironment;

public class MachineMoveCostEliminator extends AbstractComplexMove{
	ArrayList<Integer> m_id;
	static int COUNT_UPDATE=20;
	int count=0;
	
	public MachineMoveCostEliminator(SolverEnvironment env) {
		super(env);
		m_id = new ArrayList<Integer>();
	}

	@Override
	public boolean performMove() {
		boolean success = false;
//		if(count--<=0 || p_id.size()==0)
			updateM_id();
		long init_cost=getCc().getNewSolutionCost();
		Solution pot_sol = env.getPotentialSolution();
		
		Collections.shuffle(m_id,getRandom());
		
		for (Integer m: m_id){
			List<Integer> p_m = getInitial_solution().getProcessesForMachine(m);
			Collections.shuffle(p_m,getRandom());
			long local_cost=getCc().getNewSolutionCost();
			for (Integer p: p_m){
				int curr_m1_index = pot_sol.getMachineIdForProcessId(p);
				if(m==curr_m1_index)
					continue;
				//We are at different machines

				//Lets just try to move it back
				if(testWithoutMove(p,curr_m1_index, m)){
					long new_cost = local_cost +
//					long delta=
							getCc().getProcessMoveToMachineCost(pot_sol, p,curr_m1_index, m);
//					if(delta<=0){
					if(new_cost<=init_cost){
						makeMove(p,curr_m1_index, m);
						getCc().updateNewSolutionCost();
						local_cost=new_cost;
						success=true;
						continue;
					}
				}

				List<Integer> l1 = pot_sol.getProcessesForMachine(m);
				if (l1.size()==0)
					continue;
				Collections.shuffle(l1,getRandom());
				for(Integer p2:l1){
					//				if(initial_solution.getMachineIdForProcessId(p2)==orig_m1_index)
					//					continue;
					if (getIv().isProcessExchangeFeasibleNoSchedule(p,curr_m1_index, p2, m)){
						long new_cost=local_cost+getCc().getProcessExcahngeProfit(pot_sol, p,p2,curr_m1_index,m);
						if(new_cost<=init_cost){
							makeExchange(p,curr_m1_index, p2, m);
							getCc().updateNewSolutionCost();
							local_cost=new_cost;
							success=true;
							break;
						}
					}
				}//p2
			}//p
		}//m

		getCc().clearDelta();

		return success;
	}
	
	private void updateM_id(){
		m_id.clear();
		for(int _m=0;_m<getProblem().M;_m++){
			if(getCc().getMAchineMoveCost(getCurrent_solution(), _m)>0)
				m_id.add(_m);
		}
		count = COUNT_UPDATE;
	}
}
